/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.RepeatFaultElevatorListDTO;
import org.springblade.modules.admin.dto.RepeatFaultPlanListDTO;
import org.springblade.modules.admin.entity.ElevatorRepeatFaultLog;
import org.springblade.modules.admin.entity.ElevatorWxNumber;
import org.springblade.modules.admin.enums.ElevatorFaultLevelEnum;
import org.springblade.modules.admin.enums.MaintainPlanContentEnum;
import org.springblade.modules.admin.enums.TaskStatusEnum;
import org.springblade.modules.admin.mapper.ElevatorRepeatFaultLogMapper;
import org.springblade.modules.admin.service.IElevatorRepeatFaultLogService;
import org.springblade.modules.admin.service.IElevatorWxNumberService;
import org.springblade.modules.admin.service.feishu.ILarkFaultRiskMessageService;
import org.springblade.modules.admin.vo.ElevatorEffectedVO;
import org.springblade.modules.admin.vo.ElevatorRepeatFaultLogVO;
import org.springblade.modules.system.entity.TenantConfig;
import org.springblade.modules.system.service.TenantConfigService;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 人员-大屏配置 服务实现类
 *
 * @author ysq
 * @since 2024-09-26
 */
@Slf4j
@AllArgsConstructor
@Service
public class ElevatorRepeatFaultLogServiceImpl extends BaseServiceImpl<ElevatorRepeatFaultLogMapper, ElevatorRepeatFaultLog> implements IElevatorRepeatFaultLogService {

	private final IElevatorWxNumberService elevatorWxNumberService;
	private final TenantConfigService tenantConfigService;
	private final ILarkFaultRiskMessageService larkFaultRiskMessageService;

	private final static String FS_R_F_E_WEBHOOK_TEST = "https://open.feishu.cn/open-apis/bot/v2/hook/7ebcdca2-8253-4434-830a-2f466cb9a3e4";
	private final static String FS_R_F_E_WEBHOOK_PROD = "https://open.feishu.cn/open-apis/bot/v2/hook/79174abe-dc7e-4882-94b3-4fe53f19497c";

	@Override
	public IPage<ElevatorRepeatFaultLogVO> selectElevatorRepeatFaultLogPage(IPage<ElevatorRepeatFaultLogVO> page, ElevatorRepeatFaultLogVO elevatorRepeatFaultLog) {
		return page.setRecords(baseMapper.selectElevatorRepeatFaultLogPage(page, elevatorRepeatFaultLog));
	}

	@Override
	public void selectRepeatFaultElevatorPlan(List<String> tenantList) {

		List<RepeatFaultPlanListDTO> allPlanList = baseMapper.selectRepeatFaultPlanListV2(tenantList);

		List<RepeatFaultPlanListDTO> resultList = new ArrayList<>();

		tenantList.forEach(k -> {

			List<RepeatFaultPlanListDTO> tenantPlanList = allPlanList.stream().filter(e -> e.getTenantId().equals(k)).collect(Collectors.toList());
			if(Func.isNotEmpty(tenantPlanList)){
				tenantPlanList.forEach(t -> {
					RepeatFaultPlanListDTO result = new RepeatFaultPlanListDTO();
					result.setElevatorId(t.getElevatorId());
					result.setBuildingId(t.getBuildingId());
					result.setElevatorAddress(t.getElevatorAddress());
					result.setBuildingName(t.getBuildingName());
					result.setPlanId(t.getPlanId());
					result.setCreateTime(t.getCreateTime());
					result.setPlanStatusDesc(TaskStatusEnum.getTaskName(MaintainPlanContentEnum.MAINTAIN_WX.getId(), t.getPlanStatus()));
					result.setPlanUserName(t.getPlanUserName());
					result.setFaultLevel(t.getFaultLevel());
					result.setLevelDesc(ElevatorFaultLevelEnum.getName(t.getFaultLevel()));
					result.setFaultLabel(t.getFaultLabel());
					result.setFaultOverTimeDesc("否");
					if(Func.isNotEmpty(t.getFaultOvertime())){
						result.setPlanStatusDesc(TaskStatusEnum.getTaskName(MaintainPlanContentEnum.MAINTAIN_WX.getId(), t.getPlanStatus())
							+ "/请在" + t.getFaultOvertime() + "天内处理完成");
						Date planOverDate = DateUtil.offsetDay(t.getCreateTime(),t.getFaultOvertime());
						if(planOverDate.getTime() < DateUtil.date().getTime()){
							result.setFaultOverTimeDesc("是/已超时"+DateUtil.formatBetween(DateUtil.between(planOverDate, DateUtil.date(), DateUnit.MS), BetweenFormatter.Level.MINUTE));
						}
					}
					if(Func.isNotEmpty(t.getPlanRoleCodes())){
						result.setIsRole((t.getPlanRoleCodes().contains("technical_support") || t.getPlanRoleCodes().contains("expert")) ? "是" : "否");
					}
					resultList.add(result);
				});

			}
		});

		if(Func.isNotEmpty(resultList)){
			ElevatorFaultLevelEnum[] enums = ElevatorFaultLevelEnum.values();
			for (ElevatorFaultLevelEnum anEnum : enums) {
				List<RepeatFaultPlanListDTO> levelList = resultList.stream().filter(e -> e.getFaultLevel() <= anEnum.getStatus()).collect(Collectors.toList());
				if(Func.isNotEmpty(levelList)){
					larkFaultRiskMessageService.sendLarkFaultRiskMessage(anEnum.getStatus(),levelList);
				}
			}
		}

	}


	@Override
	public void selectRepeatFaultElevator(List<String> tenantList) {

		List<ElevatorEffectedVO> elevatorEffectedList = baseMapper.selectElevatorEffectedList(tenantList);
		List<ElevatorWxNumber> elevatorWxNumbers = elevatorWxNumberService.list(Wrappers.<ElevatorWxNumber>lambdaQuery().in(ElevatorWxNumber::getTenantId,tenantList).ne(ElevatorWxNumber::getStatus,0));
		if(Func.isNotEmpty(elevatorEffectedList) && Func.isNotEmpty(elevatorWxNumbers)){

			List<ElevatorRepeatFaultLog> resultList = new ArrayList<>();

			int maxDays = elevatorWxNumbers.stream().mapToInt(ElevatorWxNumber::getDays).max().getAsInt();
			String startDate = DateUtil.format(DateUtil.offsetDay(DateUtil.date(),-maxDays),"yyyy-MM-dd");
			List<RepeatFaultPlanListDTO> allPlanList = baseMapper.selectRepeatFaultPlanList(tenantList,startDate);

			// 根据租户对项目电梯分组
			Map<String,List<ElevatorEffectedVO>> tenantElevatorEffectedGroup = elevatorEffectedList.stream().collect(Collectors.groupingBy(ElevatorEffectedVO::getTenantId));
			Map<String,List<ElevatorWxNumber>> tenantElevatorWxNumberGroup = elevatorWxNumbers.stream().collect(Collectors.groupingBy(ElevatorWxNumber::getTenantId));
			tenantElevatorEffectedGroup.forEach((k,v) -> {

				ElevatorRepeatFaultLog result = new ElevatorRepeatFaultLog();
				List<RepeatFaultElevatorListDTO> recordData = new ArrayList<>();
				List<ElevatorWxNumber> tenantElevatorWxNumber = tenantElevatorWxNumberGroup.get(k).stream().sorted(Comparator.comparing(ElevatorWxNumber::getDays).thenComparing(ElevatorWxNumber::getRepetitionCounts)).collect(Collectors.toList());
				tenantElevatorWxNumber = tenantElevatorWxNumber.stream().filter(e -> e.getStatus().equals(2)).collect(Collectors.toList());
				if(Func.isNotEmpty(tenantElevatorWxNumber)){
					TenantConfig tenantConfig = tenantConfigService.getTenantConfig(k);
					// 1-任一 2-全部
					String repeatFaultElevator = String.valueOf(tenantConfig.getConfig().get("repeatFaultElevator"));
					List<RepeatFaultPlanListDTO> tenantPlanList = allPlanList.stream().filter(e -> e.getTenantId().equals(k)).collect(Collectors.toList());
					List<ElevatorWxNumber> finalTenantElevatorWxNumber = tenantElevatorWxNumber;
					v.forEach(e -> {

						List<RepeatFaultPlanListDTO> elevatorPlanList = tenantPlanList.stream().filter(p -> p.getElevatorId().equals(e.getElevatorId())).collect(Collectors.toList());
						if(Func.isNotEmpty(elevatorPlanList)){
							List<RepeatFaultPlanListDTO> finalElevatorPlanList = elevatorPlanList.stream().sorted(Comparator.comparing(RepeatFaultPlanListDTO::getCreateTime)).collect(Collectors.toList());

							RepeatFaultPlanListDTO lastPlan = finalElevatorPlanList.get(finalElevatorPlanList.size() - 1);
							// 判断条件规则
							List<String> repeatFaultLabelList = new ArrayList<>();
							List<String> repeatFaultCountLabelList = new ArrayList<>();
							finalTenantElevatorWxNumber.forEach(ex -> {
								long planCount = finalElevatorPlanList.stream().filter(p -> p.getDays() <= ex.getDays()).count();
								if(planCount > ex.getRepetitionCounts()){
									repeatFaultLabelList.add(ex.getDays() + "天" + ex.getRepetitionCounts() + "次");
								}
								repeatFaultCountLabelList.add(ex.getDays() + "天" + planCount + "次");
							});
							if((repeatFaultElevator.equals("2") && repeatFaultLabelList.size() == finalTenantElevatorWxNumber.size())
								|| (repeatFaultElevator.equals("1") && repeatFaultLabelList.size() != 0)){
								RepeatFaultElevatorListDTO entity = new RepeatFaultElevatorListDTO();
								entity.setElevatorId(e.getElevatorId());
								entity.setBuildingId(e.getBuildingId());
								entity.setElevatorAddress(e.getElevatorAddress());
								entity.setBuildingName(e.getBuildingName());
								entity.setRepeatFaultLabel(String.join(",",repeatFaultLabelList));
								entity.setRepeatFaultCountLabel(String.join(",",repeatFaultCountLabelList));
								entity.setLastFaultTime(DateUtil.formatDateTime(lastPlan.getCreateTime()));
								entity.setLastPlanUserName(lastPlan.getPlanUserName());
								entity.setLastPlanStatusDesc(TaskStatusEnum.getTaskName(MaintainPlanContentEnum.MAINTAIN_WX.getId(), lastPlan.getPlanStatus()));

								// 最小天数
								ElevatorWxNumber min = finalTenantElevatorWxNumber.get(0);
								entity.setMinDays(min.getDays());
								entity.setMinDayPlanCount(finalElevatorPlanList.stream().filter(p -> p.getDays() <= min.getDays()).count());
								entity.setMinDayPlanCountLabel(min.getDays() + "天" + finalElevatorPlanList.stream().filter(p -> p.getDays() <= min.getDays()).count() + "次");
								// 最大天数
								ElevatorWxNumber max = finalTenantElevatorWxNumber.get(finalTenantElevatorWxNumber.size() - 1);
								entity.setMaxDayPlanCount(finalElevatorPlanList.stream().filter(p -> p.getDays() <= max.getDays()).count());
								recordData.add(entity);
							}
						}
					});
				}

//				List<RepeatFaultElevatorListDTO> finalRecordData = recordData.stream().sorted(Comparator.comparing(RepeatFaultElevatorListDTO::getMinDayPlanCount)
//					.thenComparing(RepeatFaultElevatorListDTO::getMaxDayPlanCount)).collect(Collectors.toList());
				List<RepeatFaultElevatorListDTO> finalRecordData = recordData.stream().sorted(Comparator.comparing(RepeatFaultElevatorListDTO::getMinDayPlanCount,Comparator.reverseOrder())
					.thenComparing(RepeatFaultElevatorListDTO::getMaxDayPlanCount,Comparator.reverseOrder())).collect(Collectors.toList());
				result.setRecordData(finalRecordData);
				result.setTenantId(k);
				resultList.add(result);
			});

			super.saveBatch(resultList);

			ElevatorRepeatFaultLog faultLog = resultList.stream().filter(e -> "592800".equals(e.getTenantId())).findFirst().orElse(null);
			if(Func.isNotEmpty(faultLog) && Func.isNotEmpty(faultLog.getRecordData())){

				List<RepeatFaultElevatorListDTO> finalFaultLog = faultLog.getRecordData().stream().sorted(Comparator.comparing(RepeatFaultElevatorListDTO::getMinDayPlanCount,Comparator.reverseOrder())
					.thenComparing(RepeatFaultElevatorListDTO::getMaxDayPlanCount,Comparator.reverseOrder())).collect(Collectors.toList());
				List<RepeatFaultElevatorListDTO> recordDataTopTen;
				if(faultLog.getRecordData().size() > 10){
					recordDataTopTen = finalFaultLog.subList(0,10);
				}else {
					recordDataTopTen = finalFaultLog;
				}
				StringBuffer contentStr = new StringBuffer("");
				AtomicInteger index = new AtomicInteger(0);
				recordDataTopTen.forEach(e -> {
					index.addAndGet(1);
					contentStr.append(this.genContentStr(index.get(),e));
				});
				String templateStr = "{\"config\":{\"update_multi\":true},\"i18n_elements\":{\"zh_cn\":[{\"tag\":\"markdown\",\"content\":\""+ contentStr +"\",\"text_align\":\"left\",\"text_size\":\"normal\"},{\"tag\":\"action\",\"actions\":[{\"tag\":\"button\",\"text\":{\"tag\":\"plain_text\",\"content\":\"查看详情\"},\"type\":\"primary\",\"width\":\"fill\",\"size\":\"medium\",\"behaviors\":[{\"type\":\"open_url\",\"default_url\":\"\",\"pc_url\":\"https://admin.sida-tech.com/#/warningList?id="+faultLog.getId()+"\",\"ios_url\":\"\",\"android_url\":\"\"}]}]}]},\"i18n_header\":{\"zh_cn\":{\"title\":{\"tag\":\"plain_text\",\"content\":\"重复故障高风险梯预警，请及时关注并处理（统计时间：截至到"+DateUtil.formatDateTime(faultLog.getCreateTime())+"）\"},\"subtitle\":{\"tag\":\"plain_text\",\"content\":\"\"},\"template\":\"blue\"}}}";
				Map<String,Object> map = new HashMap<>();
				map.put("msg_type","interactive");
				map.put("card",templateStr);
				String result = HttpUtil.post(FS_R_F_E_WEBHOOK_PROD, JSONObject.toJSONString(map));
				log.info("请求时间:[{}],请求结果:[{}]", LocalDateTime.now(), result);
			}

		}

	}

	@Override
	public ElevatorRepeatFaultLog selectDetail(Long id) {
		return baseMapper.selectDetail(id);
	}

	@Override
	public void downExcelDetail(Long id, List<List<String>> rows) {
		ElevatorRepeatFaultLog entity = baseMapper.selectDetail(id);
		if(Func.isNotEmpty(entity.getRecordData())){
			List<RepeatFaultElevatorListDTO> recordData = entity.getRecordData();
			for (int i = 0; i < recordData.size(); i++) {
				List<String> row = new ArrayList<>(7);
				RepeatFaultElevatorListDTO dto = JSONObject.parseObject(JSONObject.toJSONString(recordData.get(i)),RepeatFaultElevatorListDTO.class);
				row.add(Convert.toStr(dto.getBuildingName()));
				row.add(Convert.toStr(dto.getElevatorAddress()));
				row.add(Convert.toStr(dto.getRepeatFaultLabel()));
				row.add(Convert.toStr(dto.getRepeatFaultCountLabel()));
				row.add(Convert.toStr(dto.getLastFaultTime()));
				row.add(Convert.toStr(dto.getLastPlanUserName()));
				row.add(Convert.toStr(dto.getLastPlanStatusDesc()));
				rows.add(row);
			}
//			recordData.forEach(elevatorDetail -> {
//				List<String> row = new ArrayList<>(7);
//				row.add(Convert.toStr(elevatorDetail.getBuildingName()));
//				row.add(Convert.toStr(elevatorDetail.getElevatorAddress()));
//				row.add(Convert.toStr(elevatorDetail.getRepeatFaultLabel()));
//				row.add(Convert.toStr(elevatorDetail.getRepeatFaultCountLabel()));
//				row.add(Convert.toStr(elevatorDetail.getLastFaultTime()));
//				row.add(Convert.toStr(elevatorDetail.getLastPlanUserName()));
//				row.add(Convert.toStr(elevatorDetail.getLastPlanStatusDesc()));
//				rows.add(row);
//			});
		}
	}

	@Override
	public List<RepeatFaultPlanListDTO> selectElevatorRepeatFaultPlanList(String level,String planStatus, Date startDate, Date endDate
		, String isOvertime, String isRole,String elevatorAddress,String elevatorDeptNames) {
		List<RepeatFaultPlanListDTO> allPlanList = baseMapper.selectRepeatFaultPlanPage();
		if(Func.isNotEmpty(allPlanList)){
			allPlanList.forEach(e -> {
				e.setPlanStatusDesc(TaskStatusEnum.getTaskName(MaintainPlanContentEnum.MAINTAIN_WX.getId(), e.getPlanStatus()));
				e.setLevelDesc(ElevatorFaultLevelEnum.getName(e.getFaultLevel()));
				e.setFaultOverTimeDesc("否");
				e.setPlanStatusDesc(TaskStatusEnum.getTaskName(MaintainPlanContentEnum.MAINTAIN_WX.getId(), e.getPlanStatus()));
				if(Func.isNotEmpty(e.getFaultOvertime())){
					Date planOverDate = DateUtil.offsetDay(e.getCreateTime(),e.getFaultOvertime());
					if(e.getPlanStatus() != TaskStatusEnum.WX_SIGN_FINISH.getStatus() && planOverDate.getTime() < DateUtil.date().getTime()){
						e.setFaultOverTimeDesc("是/已超时"+DateUtil.formatBetween(DateUtil.between(planOverDate, DateUtil.date(), DateUnit.MS), BetweenFormatter.Level.MINUTE));
					}
					if(e.getPlanStatus() == TaskStatusEnum.WX_SIGN_FINISH.getStatus() && planOverDate.getTime() < e.getPlanEndTime().getTime()){
						e.setFaultOverTimeDesc("是/已超时"+DateUtil.formatBetween(DateUtil.between(planOverDate, e.getPlanEndTime(), DateUnit.MS), BetweenFormatter.Level.MINUTE));
					}
				}
				if(Func.isNotEmpty(e.getPlanRoleCodes())){
					e.setIsRole((e.getPlanRoleCodes().contains("technical_support") || e.getPlanRoleCodes().contains("expert")) ? "是" : "否");
					e.setIsRoleName(Func.toStrList("/",e.getPlanUserName()).stream().filter(t -> t.contains("技术支持") || t.contains("维保专家")).collect(Collectors.joining("/")));
				}
			});
			if(Func.isNotEmpty(elevatorAddress)){
				allPlanList = allPlanList.stream().filter(e -> e.getElevatorAddress().contains(elevatorAddress)).collect(Collectors.toList());
			}
			if(Func.isNotEmpty(elevatorDeptNames)){
				allPlanList = allPlanList.stream().filter(e -> Func.isNotEmpty(e.getElevatorDeptNames())
					&& e.getElevatorDeptNames().contains(elevatorDeptNames)).collect(Collectors.toList());
			}
			if(Func.isNotEmpty(level)){
				allPlanList = allPlanList.stream().filter(e -> Func.toStrList(level).contains(String.valueOf(e.getFaultLevel()))).collect(Collectors.toList());
			}
			if(Func.isNotEmpty(planStatus)){
				allPlanList = allPlanList.stream().filter(e -> Func.toStrList(planStatus).contains(String.valueOf(e.getPlanStatus()))).collect(Collectors.toList());
			}
			if(Func.isNotEmpty(startDate) && Func.isNotEmpty(endDate)){
				allPlanList = allPlanList.stream().filter(e -> e.getCreateTime().getTime() >= startDate.getTime() && e.getCreateTime().getTime() <= endDate.getTime()).collect(Collectors.toList());
			}
			if(Func.isNotEmpty(isOvertime)){
				allPlanList = allPlanList.stream().filter(e -> e.getFaultOverTimeDesc().startsWith(isOvertime)).collect(Collectors.toList());
			}
			if(Func.isNotEmpty(isRole)){
				allPlanList = allPlanList.stream().filter(e -> Func.isNotEmpty(e.getIsRole()) && e.getIsRole().equals(isRole)).collect(Collectors.toList());
			}
			allPlanList = allPlanList.stream().sorted(Comparator.comparing(RepeatFaultPlanListDTO::getFaultLevel).thenComparing(RepeatFaultPlanListDTO::getCreateTime)).collect(Collectors.toList());
		}
		return allPlanList;
	}

	private String genContentStr(int index,RepeatFaultElevatorListDTO entity){
		return "**"+index+".项目梯号：**"+entity.getBuildingName()+"-"+entity.getElevatorAddress()+"\\n**"+entity.getMinDays()+"天报障总计：**"+entity.getMinDayPlanCount()+"次\\n**重复故障标签：**"+entity.getRepeatFaultLabel()+"\\n**最近报障时间/状态：**"+entity.getLastFaultTime()+"/"+entity.getLastPlanStatusDesc()+"\\n**最近工单执行人：**"+entity.getLastPlanUserName()+"\\n\\n";
	}

}
